/*
 * File:    HttpVariableStore.java
 * Created: 20-Dec-2006
 * Version: $Id$
 *
 * COPYRIGHT (C) 2006, Bitgate Software, LLC.  All Rights Reserved.
 * RELEASED UNDER THE CREATIVE COMMONS LICENSE.
 *
 * kenji@bitgatesoftware.com
 */

package com.bitgate.util.service.protocol.http;

import static com.bitgate.util.debug.Debug.debug;
import static com.bitgate.util.debug.Debug.isDebugEnabled;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Set;

/**
 * This class is a container class that stores GET and POST variables that were sent from the client to the server.  These
 * are simply used for temporary storage, and may or may not get used.  They are made available for scripts and scripting
 * engines so they can see the variables that were passed in a post, and send back for processing.
 *
 * @author Kenji Hollis &lt;kenji@bitgatesoftware.com&gt;
 * @version $Id$
 */
public class HttpVariableStore
{
    private final HashMap<String, String> getVariables;
    private final HashMap<String, String> postVariables;
    private String soapPostBody;

    /**
     * Enumerator describing the type of variables being stored.
     */
    public enum HttpStringType {
    	/** Indicates GET variables. */
    	GET,
    	
    	/** Indicates POST variables. */
    	POST,
    	
    	/** Indicates SOAP variable body data. */
    	SOAP
    }

    /**
     * Constructor.  Used by the <code>HttpClientContext</code> mainly.
     */
    public HttpVariableStore()
    {
		this.getVariables = new HashMap<String, String>();
		this.postVariables = new HashMap<String, String>();
		this.soapPostBody = null;
    }

    /**
     * Clears out the variable store.
     */
    public void clear()
    {
    	this.getVariables.clear();
    	this.postVariables.clear();
    	this.soapPostBody = null;
    }
    
    /**
     * Registers a POST variable for storage.
     *
     * @param key The post key variable name.
     * @param value The post value to store.
     */
    public void addPostVariable(String key, String value)
    {
		this.postVariables.put(key, value);
		
		if (isDebugEnabled()) {
			debug("Stored POST variable '" + key + "' with value '" + value + "'");
		}
    }

    /**
     * Registers a GET variable for storage.
     *
     * @param key The get key variable name.
     * @param value The get value to store.
     */
    public void addGetVariable(String key, String value)
    {
		this.getVariables.put(key, value);
		
		if (isDebugEnabled()) {
			debug("Stored GET variable '" + key + "' with value '" + value + "'");
		}
    }

    /**
     * Returns the POST variable stored in the specified key.
     *
     * @param key The key to look up.
     * @return <code>String</code> containing the value, <code>null</code> if not set.
     */
    public String getPostVariable(String key)
    {
    	return this.postVariables.get(key);
    }

    /**
     * Returns the GET variable stored in the specified key.
     *
     * @param key The key to look up.
     * @return <code>String</code> containing the value, <code>null</code> if not set.
     */
    public String getGetVariable(String key)
    {
    	return this.getVariables.get(key);
    }
    
    /**
     * Returns a set of known POST variables.
     * 
     * @return Set&lt;String&gt; containing the list of post variables.
     */
    public Set<String> getPostVariableKeys()
    {
    	return postVariables.keySet();
    }
    
    /**
     * Returns a set of known GET variables.
     * 
     * @return Set&lt;String&gt; containing the list of get variables.
     */
    public Set<String> getGetVariableKeys()
    {
    	return getVariables.keySet();
    }
    
    /**
     * Returns the body of the SOAP Post request (if one was made.)
     * 
     * @return <code>String</code> containing the SOAP Post request.
     */
    public String getSoapBody()
    {
    	return this.soapPostBody;
    }

    /**
     * This function takes the posted variable data, splits it by "&amp;", then key/value pairs by "=".
     *
     * @param postString The post string data.
     * @param postType The type of post string that is being sent: GET or POST.
     */
    public void parse(String postString, HttpStringType postType)
    {
		String[] postVars = postString.split("&");
	
		if (postType == HttpStringType.SOAP) {
			soapPostBody = postString;
			
			if (isDebugEnabled()) {
				debug("Soap Post Body stored in variable store.");
			}
		} else {
			for(String postVar : postVars) {
				try {
					if (postVar.indexOf("=") != -1) {
					    String[] keyValPair = postVar.split("=", 2);
				
					    if (postType == HttpStringType.GET) {
					    	addGetVariable(URLDecoder.decode(keyValPair[0], "UTF8"), URLDecoder.decode(keyValPair[1], "UTF8"));
					    } else if (postType == HttpStringType.POST) {
					    	addPostVariable(URLDecoder.decode(keyValPair[0], "UTF8"), URLDecoder.decode(keyValPair[1], "UTF8"));
					    }
					} else {
						if (postType == HttpStringType.GET) {
							addGetVariable(URLDecoder.decode(postVar, "UTF8"), "");
						} else if (postType == HttpStringType.POST) {
							addPostVariable(URLDecoder.decode(postVar, "UTF8"), "");
						}
					}
				} catch(UnsupportedEncodingException ex) {
					debug("Unable to decode post/get vars via UTF-8: " + ex.getMessage());
				}
			}
			
			if (isDebugEnabled()) {
				debug("Post variable '" + postString + "' contains " + postVars.length + " entries.");
			}
		}
    }
}
